﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Reflection;
using System.Runtime.Remoting;
using System.Threading;
using AkazoNobel.Scheduler.StoreMasterData.DataAccess;
using AkazoNobel.Scheduler.StoreMasterData.DataAccess.Model;
using AkazoNobel.Scheduler.StoreMasterData.DataAccess.Service;
using AkazoNobel.Ultimus.Extension;
using Dapper;
using log4net;
using Ultimus.OC;
using Ultimus.WFServer;

namespace AkazoNobel.Scheduler.StoreMasterData.Common
{
    public static class TaskHelper
    {
        /// <summary>
        /// 日志记录
        /// </summary>
        private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        /// <summary>
        /// 发起一个新流程
        /// </summary>
        /// <param name="applicator"></param>
        /// <param name="process"></param>
        /// <param name="summary"></param>
        /// <param name="variables"></param>
        /// <param name="applicationNo"></param>
        /// <returns></returns>
        public static int NewIncident(string applicator, string process, string summary, List<Variable> variables, out string applicationNo)
        {
            var arrUserName = new string[1];
            arrUserName[0] = applicator;

            var initiateId = GetInitiateId(process);
            if (string.IsNullOrEmpty(initiateId))
            {
                applicationNo = "";
                return 0;
            }
            var task = new Task();
            var incident = 0;
            applicationNo = "";
            if (task.InitializeFromTaskId(initiateId))
            {
                var now = System.DateTime.Now;
                applicationNo = SequenceService.Generate(task.GetString("PrefixNo") + "-" + now.ToString("yyMM"), "", 4);
                variables.Add("ApplicationNO", applicationNo);
                variables.Add("Time", now.ToString("yyyy.MM.dd HH:mm:ss"));

                var ocUser = GetOcUser(applicator);
                variables.Add("Applicator", applicator);
                variables.Add("ApplicatorName", ocUser == null ? "" : ocUser.strUserFullName);
                variables.Add("Department", ocUser == null ? "" : ocUser.strDepartmentName);
                variables.Add("Remark_by_Initiator", "程序自动启动流程");

                string strError;
                Console.WriteLine("-->>SendFrom start");
                if (!task.SendFrom(applicator, variables.ToArray(), summary, summary, ref incident, out strError) || strError != "")
                {
                    Logger.Error(strError);
                }
                else
                {
                    Logger.Debug("发起新流程：" + process + "[" + incident + "]");
                }
                Console.WriteLine("-->>SendFrom end");
            }
            else
            {
                Logger.Error("流程加载失败！" + "P:" + process + " U:" + applicator);
            }

            return incident;
        }

        /// <summary>
        /// 删除流程实例
        /// </summary>
        /// <param name="processName"></param>
        /// <param name="incidentNo"></param>
        public static void DeleteIncident(string processName, int incidentNo, string winId)
        {
            var incident = new Incident();
            incident.LoadIncident(processName, incidentNo);

            var strError = "";
            incident.AbortIncident(winId, "自动发起流程业务数据写入失败", out strError);
            if (strError != "")
            {
                incident.DeleteIncident(out strError);
            }
        }

        /// <summary>
        /// 根据流程名，实例号获取TaskID
        /// </summary>
        /// <param name="process">流程名</param>
        /// <param name="incident">实例号</param>
        /// <param name="step">步骤名，默认第一个步骤</param>
        /// <returns>TaskID</returns>
        public static string GetTaskId(string process, int incident, string step = "")
        {
            var filter = new TasklistFilter
            {
                strProcessNameFilter = process,
                nIncidentNo = incident
            };

            if (step != "")
            {
                filter.strStepLabelFilter = step;
            }

            var taskList = new Tasklist();
            taskList.LoadFilteredTasks(filter);
            var task = taskList.GetFirstTask();

            return task == null ? "" : task.strTaskId;
        }

        /// <summary>
        /// 根据流程名，实例号获取Task
        /// </summary>
        /// <param name="process">流程名</param>
        /// <param name="incident">实例号</param>
        /// <param name="step">步骤名，默认第一个步骤</param>
        /// <returns>task</returns>
        public static Task GetTask(string process, int incident, string[] arrUserName, string step = "")
        {
            
            var filter = new TasklistFilter
            {
                strProcessNameFilter = process,
                nIncidentNo = incident,
                strArrUserName = arrUserName
            };

            if (step != "")
            {
                filter.strStepLabelFilter = step;
            }

            var taskList = new Tasklist();
            taskList.LoadFilteredTasks(filter);

            return taskList.GetFirstTask();
        }

        /// <summary>
        /// 根据用户名获取OC中的用户信息
        /// </summary>
        /// <param name="username">用户名</param>
        /// <returns>OC User</returns>
        public static User GetOcUser(string username)
        {
            var oc = new OrgChart();
            User ocUser;
            oc.FindUser(username, "", 0, out ocUser);

            return ocUser;
        }

        /// <summary>
        /// 审批意见设置
        /// </summary>
        /// <param name="winId"></param>
        /// <param name="process"></param>
        /// <param name="incident"></param>
        /// <param name="step"></param>
        /// <param name="autoBusinessKey"></param>
        /// <param name="conn"></param>
        /// <returns></returns>
        public static Assessment SetAssessment(string winId, string process, int incident, string step, string autoBusinessKey, SqlConnection conn, SqlTransaction trans)
        {
            var ocUser = GetOcUser(winId);
            var random = new Random();
            var assessment = new Assessment
            {
                ID = System.DateTime.Now.ToString("yyyyMMddhhmmssfff") + random.Next(1000, 9999),
                Process = process,
                Incident = incident,
                Step = step,
                UserName = ocUser == null ? "" : ocUser.strUserName,
                UserFullName = ocUser == null ? "" : ocUser.strUserFullName,
                AssignedToUserName = ocUser == null ? "" : ocUser.strUserName,
                AssignedToUserFullName = ocUser == null ? "" : ocUser.strUserFullName,
                Department = ocUser == null ? "" : ocUser.strDepartmentName,
                StartTime = System.DateTime.Now,
                Time = System.DateTime.Now,
                Opinion = "",
                OpinionText = "",
                Opinion2 = "",
                OpinionText2 = "",
                Status = 1,
                Remark = "",
                BusinessProcess = autoBusinessKey
            };

            // 初始化业务流程KEY
            var key = "";
            const string num = "0001";
            switch (assessment.BusinessProcess)
            {
                case "DegradeStore":
                    key = "SD";
                    break;
                case "Store":
                    key = "NS";
                    break;
                case "DataChange":
                    key = "MC";
                    break;
                case "MDCItss":
                    key = "BH";
                    break;
            }
            var timeKey = key + DateTime.Now.Year.ToString() + (DateTime.Now.Month < 10 ? "0" + DateTime.Now.Month.ToString() : DateTime.Now.Month.ToString());
            var lastAssessment = AssessmentService.GetLastLikeKey(timeKey);

            if (lastAssessment != null)
            {
                var businessKey = lastAssessment.BusinessKey;
                var numBak = Convert.ToInt32(businessKey.Substring(businessKey.Length - 4)) + 1;
                var numKey = numBak.ToString();
                for (var s = numBak.ToString().Length; s < 4; s++)
                {
                    numKey = "0" + numKey;
                }
                timeKey += numKey;
            }
            else
            {
                timeKey += num;
            }
            assessment.BusinessKey = timeKey;


            conn.Execute(
                "INSERT INTO t_Assessment(ID,Process,Incident,Step,UserName,UserFullName,AssignedToUserName,AssignedToUserFullName,Department,Signature,Opinion,Opinion2,OpinionText,OpinionText2,Remark,StartTime,Time,ReturnTo,Status,BusinessProcess,BusinessKey)" +
                "VALUES(@ID,@Process,@Incident,@Step,@UserName,@UserFullName,@AssignedToUserName,@AssignedToUserFullName,@Department,@Signature,@Opinion,@Opinion2,@OpinionText,@OpinionText2,@Remark,@StartTime,@Time,@ReturnTo,@Status,@BusinessProcess,@BusinessKey)",
                assessment, trans);

            return assessment;

        }

        public static Incident GetIncident(string process, int incidentNo)
        {
            var incident = new Incident();
            try
            {
                if (incident.LoadIncident(process, incidentNo))
                {
                    return incident;
                }
            }
            catch (Exception ex)
            {
                if (incident.LoadIncident(process, incidentNo))
                {
                    return incident;
                }

                Logger.Error(ex.Message);
                return null;
            }

            return null;
        }

        /// <summary>
        /// 从数据库中获取初始TaskId，用于发起流程
        /// </summary>
        /// <param name="process"></param>
        /// <returns></returns>
        public static string GetInitiateId(string process)
        {
            var initiateId = "";
            using (var connUltimus = SqlConnectionHelper.GetConnection(Constant.ULTIMUS_DB_NAME))
            {
                initiateId = connUltimus.Query<string>("SELECT RTRIM(INITIATEID) FROM INITIATE WHERE PROCESSNAME = @Process", new {Process = process}).FirstOrDefault();
            }

            if (string.IsNullOrEmpty(initiateId))
            {
                Logger.Error("找不到此流程的相关信息！" + process);
            }
            return initiateId;
        }
      
    }
}